﻿#include "widget.h"
#include "ui_widget.h"
#include<QDataStream>
#include<QMessageBox>
#include<QDateTime>
#include<QTableWidget>
#include<QComboBox>
#include<QFont>
#include<QColorDialog>
#include<QFileDialog>
#include<QDebug>

Widget::Widget(QWidget *parent, QString name) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->myname = name;
    port = 9999;
    udpSocket = new QUdpSocket(this);
    // 允许其他服务器连接相同端口和地址|重新连接服务器
    udpSocket->bind(port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);

    // 窗口基础设置
    this->setMinimumSize(800, 500); // 最小尺寸
    this->setWindowTitle(name + " - QT聊天");

    // 整体样式
    this->setStyleSheet("QWidget { font-family: 'Microsoft YaHei'; font-size: 12px; }");

    // 消息显示区样式
    ui->msgBrowser->setStyleSheet(
        "QTextBrowser {"
        "background-color: #F9F9F9;"
        "border: 1px solid #EEE;"
        "border-radius: 4px;"
        "padding: 10px;"  // 消息区整体内边距
        "}"
        "QTextBrowser span, QTextBrowser p {"  // 只清除span和p的边距，不影响div
        "margin: 0; "
        "padding: 0; "
        "}"
        );
    ui->msgBrowser->setOpenExternalLinks(false); // 禁止外部链接

    // 工具栏样式
    ui->frame_2->setStyleSheet("background-color: #F5F7FA; border: 1px solid #E1E4E8;");
    // 按钮统一样式
    QString toolBtnStyle = "QToolButton { border: none; padding: 5px; border-radius: 3px; }"
                           "QToolButton:hover { background-color: #E8F0FE; }"
                           "QToolButton:pressed { background-color: #D7E8FC; }";
    ui->underlineTbtn->setStyleSheet(toolBtnStyle);
    ui->boldBtn->setStyleSheet(toolBtnStyle);
    ui->italicTbtn->setStyleSheet(toolBtnStyle);
    ui->colorTbtn->setStyleSheet(toolBtnStyle);
    ui->saveTbtn->setStyleSheet(toolBtnStyle);
    ui->clearTbtn->setStyleSheet(toolBtnStyle);

    // 输入区
    ui->msgTxtEdit->setStyleSheet("border: 1px solid #CCC; border-radius: 4px; padding: 5px;");
    ui->msgTxtEdit->setMinimumHeight(80);

    // 按钮样式
    ui->sendBtn->setStyleSheet("QPushButton { background-color: #2B79D9; color: white; border: none; padding: 6px 15px; border-radius: 4px; }"
                               "QPushButton:hover { background-color: #3A89E9; }"
                               "QPushButton:pressed { background-color: #1A69C9; }");
    ui->exitBtn->setStyleSheet("QPushButton { background-color: #F0F2F5; color: #333; border: 1px solid #DDD; padding: 6px 15px; border-radius: 4px; }"
                               "QPushButton:hover { background-color: #E5E7EB; }");

    // 用户列表
    ui->tableWidget->setStyleSheet("QTableWidget { border: 1px solid #EEE; border-radius: 4px; }"
                                   "QHeaderView::section { background-color: #F5F7FA; padding: 5px; border: 1px solid #EEE; }"
                                   "QTableWidget::item { padding: 5px; }"
                                   "QTableWidget::item:selected { background-color: #E8F0FE; color: #333; }");
    ui->tableWidget->horizontalHeader()->setStretchLastSection(true); // 列自适应

    // 在线人数标签
    ui->userNumLbl->setStyleSheet("color: #666;");

    // 发送按钮
    connect(ui->sendBtn, &QPushButton::clicked, this, [=](){
        sendMsg(Msg);
    });
    // 监听别人发送的数据
    connect(udpSocket, &QUdpSocket::readyRead, this, &Widget::receiveMessage);
    // 新用户进入
    sendMsg(UserEnter);
    connect(ui->exitBtn, &QPushButton::clicked, this, &Widget::close);

    // 字体F
    connect(ui->fontCbx,&QFontComboBox::currentFontChanged,this,[=](const QFont &font){
        // 设置全局字体
        ui->msgTxtEdit->setFontFamily(font.toString());
        ui->msgTxtEdit->setFocus();
    });

    // 字体大小
    void (QComboBox:: *sizeBtn)(const QString &text)=&QComboBox::currentTextChanged;
    connect(ui->sizeCbx,sizeBtn,this,[=](const QString &text){
        ui->msgTxtEdit->setFontPointSize(text.toDouble());
        ui->msgTxtEdit->setFocus();
    });

    // 加粗
    connect(ui->boldBtn,&QToolButton::clicked,this,[=](bool checked){
        // 是否按下
        if(checked){
            ui->msgTxtEdit->setFontWeight(QFont::Bold);
        }else{
            ui->msgTxtEdit->setFontWeight(QFont::Normal);
        }
    });

    // 倾斜
    connect(ui->italicTbtn,&QToolButton::clicked,this,[=](bool checked){
        ui->msgTxtEdit->setFontItalic(checked);
        ui->msgTxtEdit->setFocus();
    });

    // 下划线
    connect(ui->underlineTbtn,&QToolButton::clicked,this,[=](bool checked){
        ui->msgTxtEdit->setFontUnderline(checked);
        ui->msgTxtEdit->setFocus();
    });

    // 字体颜色
    connect(ui->colorTbtn,&QToolButton::clicked,this,[=](){
        QColor color=QColorDialog::getColor(color,this);
        ui->msgTxtEdit->setTextColor(color);
    });

    // 保存聊天记录
    connect(ui->saveTbtn,&QToolButton::clicked,this,[=](){
        if(ui->msgBrowser->toPlainText().isEmpty()){
            QMessageBox::warning(this,"警告","保存内容不能为空");
            return;
        }
        // 获取保存文件绝对路径/文件名(窗口标题,文件名,类型)
        QString fileName=QFileDialog::getSaveFileName(this,"保存聊天记录","聊天记录","(*.txt)");
        if(!fileName.isEmpty()){
            QFile file(fileName);

            if (!file.open(QIODevice::WriteOnly | QFile::Text)) {
                qWarning() << "无法打开文件：" << file.errorString();
                return;
            }

            QTextStream stream(&file);
            stream<<ui->msgBrowser->toPlainText();
            file.close();
        }
    });

    // 清空聊天记录
    connect(ui->clearTbtn,&QToolButton::clicked,this,[=](){
        ui->msgBrowser->clear();
    });
}

void Widget::closeEvent(QCloseEvent *)
{
    emit closeWidget();
    sendMsg(UserLeft);
    udpSocket->close();
    udpSocket->destroyed();
}

QString Widget::getName()
{
    return myname;
}

QString Widget::getMsg()
{
    QString msg = ui->msgTxtEdit->toPlainText();
    ui->msgTxtEdit->clear();
    ui->msgTxtEdit->setFocus();
    return msg;
}

// 用户上线通知
void Widget::userEnter(QString username, QString time)
{
    bool IsEmpty=ui->tableWidget->findItems(username,Qt::MatchExactly).isEmpty();
    if(IsEmpty)
    {
        QTableWidgetItem *table=new QTableWidgetItem(username);
        ui->tableWidget->insertRow(0);
        ui->tableWidget->setItem(0,0,table);
        QString systemHtml = QString(
                                 "<div style='width:100%; margin:10px 0; padding:5px 0;'>"
                                 "<hr style='border:1px dashed #EEE; margin:5px 0;'>"  // 用<hr>替代div的border
                                 "<p style='text-align:center; color:#999; font-size:11px; margin:0 auto; width:100%;'>"
                                 "%1 于 %2 上线"
                                 "</p>"
                                 "<hr style='border:1px dashed #EEE; margin:5px 0;'>"
                                 "</div><br/>"
                                 ).arg(username.toHtmlEscaped()).arg(time);
        ui->msgBrowser->insertHtml(systemHtml);
        ui->userNumLbl->setText(QString("在线人数:%1").arg(ui->tableWidget->rowCount()));
    }
}

// 用户下线通知
void Widget::userLeft(QString username, QString time)
{
    bool isEmpty=ui->tableWidget->findItems(username,Qt::MatchExactly).isEmpty();
    if(!isEmpty){
        int row=ui->tableWidget->findItems(username,Qt::MatchExactly).first()->row();
        ui->tableWidget->removeRow(row);
        QString systemHtml = QString(
                                 "<div style='width:100%; margin:10px 0; padding:5px 0; border-top:1px dashed #EEE; border-bottom:1px dashed #EEE;'>"
                                 "<p style='text-align:center; color:#999; font-size:11px; margin:0 auto; width:100%; white-space:normal;'>"  // 新增margin:0 auto和width:100%
                                 "%1 于 %2 下线"
                                 "</p>"
                                 "</div><br/>"
                                 ).arg(username.toHtmlEscaped()).arg(time);
        ui->msgBrowser->insertHtml(systemHtml);
        ui->userNumLbl->setText(QString("在线人数:%1").arg(ui->tableWidget->rowCount()));
    }
}

// 1. 修改 sendMsg 函数，所有类型都包含“类型+用户名+时间/内容”
void Widget::sendMsg(Widget::msgType type)
{
    QByteArray array;
    QDataStream stream(&array,QIODevice::WriteOnly);
    QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"); // 统一添加时间
    stream << type << this->getName() << time; // 固定顺序：类型→用户名→时间
    switch (type)
    {
    case Msg:
        if(ui->msgTxtEdit->toPlainText().isEmpty()){
            QMessageBox::warning(this,"警告","发送的聊天内容不能为空!");
            return;
        }
        stream << this->getMsg(); // 消息类型额外添加：内容
        break;
    case UserEnter:
        break;
    case UserLeft:
        break;
    }
    udpSocket->writeDatagram(array.data(), array.size(), QHostAddress::Broadcast, port);
}

// 2. 修改 receiveMessage 函数，按“类型→用户名→时间→内容”顺序读取
void Widget::receiveMessage()
{
    qint64 size = udpSocket->pendingDatagramSize();
    QByteArray array = QByteArray(size, 0);
    udpSocket->readDatagram(array.data(), size);
    QDataStream stream(&array, QIODevice::ReadOnly);
    int mytype;
    QString name, time, msg; // 新增time变量，统一接收时间
    stream >> mytype >> name >> time; // 固定顺序：先读类型→用户名→时间

    switch (mytype) {
    case Msg: {
        stream >> msg;
        QString html;
        if (name == myname) {
            // 自己的消息
            html = QString(
                       "<table width='100%' style='margin:10px 0; border-collapse:collapse;'>"  // 表格占满宽度，无边框
                       "<tr>"
                       // 用户名+时间单元格：强制右对齐，无内边距
                       "<td align='right' style='padding:0 0 3px 0; color:#666; font-size:11px;'>"
                       "%1 %2"
                       "</td>"
                       "</tr>"
                       "<tr>"
                       // 消息内容单元格：右对齐，确保气泡靠右
                       "<td align='right' style='padding:0;'>"
                       "<span style='background-color:#95EC69; padding:6px 10px; border-radius:6px; "
                       "display:inline-block; max-width:70%; word-wrap:break-word; white-space:normal;'>"
                       "%3"
                       "</span>"
                       "</td>"
                       "</tr>"
                       "</table><br/>"
                       ).arg(name.toHtmlEscaped()).arg(time).arg(msg.toHtmlEscaped());
        } else {
            // 他人的消息
            html = QString(
                       "<div style='width:100%; margin:10px 0; overflow:hidden;'>"
                       "<div style='text-align:left; margin-bottom:3px;'>"
                       "<span style='color:#666; font-size:11px;'>%1 %2</span>"
                       "</div>"
                       "<div style='text-align:left;'>"
                       "<span style='background-color:white; border:1px solid #DDD; padding:6px 10px; border-radius:6px; "
                       "display:inline-block; max-width:70%; word-wrap:break-word; white-space:normal;'>"
                       "%3"
                       "</span>"
                       "</div>"
                       "</div><br/>"
                       ).arg(name.toHtmlEscaped()).arg(time).arg(msg.toHtmlEscaped());
        }
        ui->msgBrowser->insertHtml(html);
        break;
    }
    case UserEnter: {
        userEnter(name, time);
        break;
    }
    case UserLeft: {
        userLeft(name, time);
        break;
    }
    }
    ui->msgBrowser->moveCursor(QTextCursor::End);
}

Widget::~Widget()
{
    delete ui;
}
